#ifndef _colorspace_h_
#define _colorspace_h_

// colorspace.h
//
//  Color space conversion functions


#include "image/imageTypes.h"

#include <math.h>  // acos

namespace simple{
    //
    // Color Plane
    //

    template<class T>
    Image<T> colorPlane1 (Image<RGBTmpl<T> >& image)
    {
        Image<T> dst (image.boundary());

        typename Image<RGBTmpl<T> >::row_iterator i1 = image.row_begin();
        typename Image<T>::row_iterator i2 = dst.row_begin();

        int width = image.width();
        int x;

        const RGBTmpl<T>* pels;
        T* peld;

        for (; i1!=image.row_end(); i1++, i2++) {
            pels = i1->p;
            peld = i2->p;
            for (x=0; x<width; x++) {
                *peld++ = pels->red;
                pels++;
            }
        }
        return dst;
    }

    template<class T>
    Image<T> colorPlane2 (Image<RGBTmpl<T> >& image)
    {
        Image<T> dst (image.boundary());

        typename Image<RGBTmpl<T> >::row_iterator i1 = image.row_begin();
        typename Image<T>::row_iterator i2 = dst.row_begin();

        int width = image.width();
        int x;

        const RGBTmpl<T>* pels;
        T* peld;

        for (; i1!=image.row_end(); i1++, i2++) {
            pels = i1->p;
            peld = i2->p;
            for (x=0; x<width; x++) {
                *peld++ = pels->green;
                pels++;
            }
        }
        return dst;
    }

    template<class T>
    Image<T> colorPlane3 (Image<RGBTmpl<T> >& image)
    {
        Image<T> dst (image.boundary());

        typename Image<RGBTmpl<T> >::row_iterator i1 = image.row_begin();
        typename Image<T>::row_iterator i2 = dst.row_begin();

        int width = image.width();
        int x;

        const RGBTmpl<T>* pels;
        T* peld;

        for (; i1!=image.row_end(); i1++, i2++) {
            pels = i1->p;
            peld = i2->p;
            for (x=0; x<width; x++) {
                *peld++ = pels->blue;
                pels++;
            }
        }
        return dst;
    }



    
    //
    // HSI
    //
    typedef RGBTmpl<Pel8>   HSI;
    typedef RGBTmpl<Pel32>  HSIPel32;
    typedef RGBTmpl<Pel32s> HSIPel32s;   // This is signed!!

    template<class T>
    RGBTmpl<T> RGB2HSI (const RGBTmpl<T>& pel)
    {
        static double twoPi = asin(1.) * 4.;

        RGBTmpl<T> hsi;
        double t;
        
        T r = pel.red;
        T g = pel.green;
        T b = pel.blue;

        if (r==g && r==b && g==b) // Degenerate case. Grayscale
            return RGBTmpl<T> (0, 0, r);

        // Hue
        t = acos(.5 * ((r-g)+(r-b)) / sqrt((r-g)*(r-g) + (r-b)*(g-b)));
        double sum = r+g+b;
        if (b > g) t = twoPi - t;  // 2*pi - t; Gives us 4 quadrant answer
        hsi.red = static_cast<T>(t * apLimitInfo<T>::sType.maxValue / twoPi);

        // Saturation
        t = 1. - 3. * min(r, min(g, b)) / sum;
        hsi.green = static_cast<T>(t * apLimitInfo<T>::sType.maxValue);

        // Intensity
        hsi.blue = (r + g + b) / 3;

        return hsi;
    }


    template<class T>
    void RGB2HSI (Image<RGBTmpl<T> >& image)
    {
        typename Image<RGBTmpl<T> >::row_iterator i;

        unsigned int width = image.width();
        unsigned int x;
        RGBTmpl<T>* p;
        RGBTmpl<T> pel;
        for (i=image.row_begin(); i!=image.row_end(); i++) {
            p = i->p;
            for (x=0; x<width; x++) {
                pel = *p;
                *p++ = RGB2HSI (pel);
                //  *p++ = *p;
                //  *p++ = RGB2HSI (*p);
            }
        }
      }

}

#endif // _colorspace_h_
